package com.gollum.web.service;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.core.math.Calculator;
import com.gollum.common.constant.GollumCacheConstants;
import com.gollum.common.constant.SysConfigConstants;
import com.gollum.common.enums.Operator;
import com.gollum.common.exception.BusinessException;
import com.gollum.common.utils.EncrypUtils;
import com.gollum.common.utils.HandleConverUtils;
import com.gollum.common.utils.StringUtils;
import com.gollum.common.utils.redis.RedisCache;
import com.gollum.system.domain.response.LoginUser;
import com.gollum.manager.AsyncManager;
import com.gollum.manager.factory.LogAsyncFactory;
import com.gollum.system.service.SysConfigService;
import com.gollum.system.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 认证服务
 *
 * @author Herther
 * @version 1.0.0
 * @createTime 2022年08月27日 22:33:00
 */
@Component
@SuppressWarnings("all")
public class AuthService {


    @Autowired
    protected TokenService tokenService;

    @Resource
    protected AuthenticationManager authenticationManager;

    @Autowired
    protected RedisCache redisCache;

    @Autowired
    protected SysUserService userService;

    @Autowired
    protected SysConfigService sysConfigService;


    /**
     * 登录验证
     *
     * @param username 用户名
     * @param password 密码
     * @return 结果
     */
    public String login(String username, String password,String code,String token) {
        Boolean hasEnableCaptcha
                = HandleConverUtils.strToBoolean(sysConfigService.getConfigValue(SysConfigConstants.SYS_CONFIG_ENABLECAPTCHA));
        //判断验证码是否开启
        if (!hasEnableCaptcha){
            try {
                validateCaptcha(code,token);
            }catch (BusinessException e){
                AsyncManager.me()
                        .execute(LogAsyncFactory.saveLogininfor(username,Operator.ERROR.getValue(), e.getMessage()));
                throw new BusinessException("验证码不正确");
            }
        }
        // 用户验证
        Authentication authentication = null;
        try {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(username,  EncrypUtils.privateDecrypt(password)));
        }
        catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                AsyncManager.me()
                        .execute(LogAsyncFactory.saveLogininfor(username,Operator.ERROR.getValue(), "密码有误"));
                throw new BusinessException("用户名密码不正确");
            }
            if (e instanceof BusinessException){
                AsyncManager.me()
                        .execute(LogAsyncFactory.saveLogininfor(username, Operator.ERROR.getValue(), e.getMessage()));
                throw new BusinessException("用户名密码不正确");
            }
            if (e instanceof InternalAuthenticationServiceException){
                AsyncManager.me()
                        .execute(LogAsyncFactory.saveLogininfor(username,Operator.ERROR.getValue(), "用户不存在"));
                throw new BusinessException("用户名密码不正确");
            }
        }
        AsyncManager.me()
                .execute(LogAsyncFactory.saveLogininfor(username, Operator.SUCCESS.getValue(),"登录成功"));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 生成token
        return tokenService.createToken(loginUser);
    }

    /**
     * 验证码校验
     *
     * @param
     * @return
     * @auther: Herther
     * @version 1.0.0
     * @date: 2022/9/4 22:31
     */
    public void validateCaptcha(String code, String token){
        if (StringUtils.isAnyEmpty(code,token)){
            throw new BusinessException("验证码不存在");
        }
        //校验数字类型
        int codeInt;
        try {
            codeInt = Integer.parseInt(code);
        } catch (NumberFormatException e) {
            // 用户输入非数字
            throw new BusinessException("验证码有误");
        }
        //拼接redisKey
        StringBuffer key = new StringBuffer(GollumCacheConstants.CAPTCHA_GRAP_KEY)
                .append(token);
        //获取redis Key
        String captchaValue = redisCache.getCacheObject(key.toString());
        if (StringUtils.isEmpty(captchaValue)){
            //验证码不存在
            throw new BusinessException("验证码不存在");
        }
        //验证码校验
        final int calculateResult = (int) Calculator.conversion(captchaValue);
        if (codeInt != calculateResult){
            throw new BusinessException("验证码有误");
        }
        //删除key 校验成功
        redisCache.deleteObject(key.toString());
    }
}
